﻿using System.Reflection;
using System.Windows;
using System.Windows.Controls;

namespace WPF_PasswordBox
{
    public class PasswordBoxHelper
    {
        /// <summary>
        /// DependencyObject‌：作为依赖属性系统的基类，提供属性值获取（GetValue）、设置（SetValue）等基础功能，并负责属性元数据管理。所有支持依赖属性的WPF控件（如TextBox、Button等）均继承自该类。
        /// DependencyProperty‌：用于注册依赖属性，提供属性标识符和元数据定义。开发者通过调用Register方法创建依赖属性注册信息，并生成DependencyProperty实例。
        /// </summary>
        public static readonly DependencyProperty PwdProperty = DependencyProperty.RegisterAttached(
            "Pwd", typeof(String), typeof(PasswordBoxHelper), new PropertyMetadata(String.Empty, OnPwdPropertyChanged));

        public static void SetPwd(DependencyObject obj, String value)
        {
            // 这个obj就是界面控件实例，在这里是PasswordBox
            obj.SetValue(PwdProperty, value);
        }

        public static String GetPwd(DependencyObject obj)
        {
            return (String)obj.GetValue(PwdProperty);
        }

        private static void OnPwdPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PasswordBox pwdBox = d as PasswordBox;
            if (pwdBox == null)
            {
                return;
            }

            pwdBox.Password = (String)e.NewValue;
            // 赋值后，移动光标到最后一位
            SetSelection(pwdBox, pwdBox.Password.Length, 0);
        }

        public static readonly DependencyProperty IsEnablePasswordPropertyChangedProperty =
            DependencyProperty.RegisterAttached(
                "IsEnablePasswordPropertyChanged", typeof(bool), typeof(PasswordBoxHelper),
                new PropertyMetadata(false, OnPasswordPropertyChanged));


        public static void SetIsEnablePasswordPropertyChanged(DependencyObject obj, bool value)
        {
            obj.SetValue(IsEnablePasswordPropertyChangedProperty, value);
        }

        public static bool GetIsEnablePasswordPropertyChanged(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsEnablePasswordPropertyChangedProperty);
        }

        private static void OnPasswordPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PasswordBox pwdBox = d as PasswordBox;
            if (pwdBox == null)
            {
                return;
            }

            if ((bool)e.NewValue)
            {
                pwdBox.PasswordChanged += MyPasswordPropertyChanged;
            }
            else
            {
                pwdBox.PasswordChanged -= MyPasswordPropertyChanged;
            }
        }

        private static void MyPasswordPropertyChanged(object sender, RoutedEventArgs e)
        {
            PasswordBox pwdBox = (PasswordBox)sender;
            SetPwd(pwdBox, pwdBox.Password);
        }

        /// <summary>
        /// 设置光标位置
        /// </summary>
        /// <param name="pwdBox"></param>
        /// <param name="start">光标开始位置</param>
        /// <param name="length">选中长度</param>
        private static void SetSelection(PasswordBox pwdBox, int start, int length)
        {
            pwdBox.GetType()
                .GetMethod("Select", BindingFlags.Instance | BindingFlags.NonPublic)
                .Invoke(pwdBox, new object[] { start, length });
        }
    }
}